#include "Int_24C256.h"

// 浮点数转整数（保留2位小数）
static int32_t Float_To_Int(float value)
{
    return (int32_t)(value * FLOAT_SCALE + 0.5f); // +0.5f用于四舍五入
}

// 整数转浮点数（恢复2位小数）
static float Int_To_Float(int32_t value)
{
    return (float)value / FLOAT_SCALE;
}

uint8_t Int_24C256_SaveData(int32_t circle, float part_int, float displacement)
{
    DataRecord_t new_record, last_record;
    uint8_t current_pointer;
    uint8_t last_record_index;
    uint16_t last_record_address;
    uint16_t next_address;

    new_record.circle_count = circle;
    new_record.displacement_int = Float_To_Int(displacement);
    new_record.part_int = Float_To_Int(part_int);
    new_record.checksum = Calculate_Checksum(&new_record);

    // 读取当前指针位置
    Int_24C256_ReadData(POINTER_ADDRESS, &current_pointer, 1);

    // 3. 检查指针有效性
    if (current_pointer >= MAX_RECORDS)
    {
        current_pointer = 0; // 重置到起始位置
    }

    // 4. 读取上一次的数据进行比较
    if (current_pointer == 0)
    {
        last_record_index = MAX_RECORDS - 1; // 指针在0，上次数据在最后位置
    }
    else
    {
        last_record_index = current_pointer - 1; // 上次数据在指针前一位置
    }

    last_record_address = DATA_STORAGE_START + (last_record_index * RECORD_SIZE);
    Int_24C256_ReadData(last_record_address, (uint8_t *)&last_record, RECORD_SIZE);

    // 5. 验证上次数据完整性
    uint32_t last_checksum = Calculate_Checksum(&last_record);
    if (last_checksum == last_record.checksum)
    {
        // 6. 比较数据是否相同（整数比较，精确可靠）
        if (last_record.circle_count == new_record.circle_count &&
            last_record.part_int == new_record.part_int &&
            last_record.displacement_int == new_record.displacement_int)
        {

            debug_printfln("Data unchanged, skip writing");
            return 2; // 返回2表示数据未变化，跳过写入
        }
    }

    // 7. 数据不同或上次数据损坏，执行写入
    next_address = DATA_STORAGE_START + (current_pointer * RECORD_SIZE);
    Int_24C256_WriteData(next_address, (uint8_t *)&new_record, RECORD_SIZE);

    // 8. 更新指针
    current_pointer = (current_pointer + 1) % MAX_RECORDS;
    Int_24C256_WriteData(POINTER_ADDRESS, &current_pointer, 1);

    debug_printfln("Data saved: circle=%d, angle=%.2f, disp=%.2f",
                   circle, Int_To_Float(new_record.part_int),
                   Int_To_Float(new_record.displacement_int));
    return 1; // 成功写入
}

uint8_t Int_24C256_LoadLatestData(int32_t *circle, float *part_int, float *displacement)
{
    DataRecord_t record;
    uint8_t current_pointer;
    uint8_t last_record_index;
    uint16_t read_address;

    // 1. 读取当前指针
    Int_24C256_ReadData(POINTER_ADDRESS, &current_pointer, 1);

    // 2. 计算最新记录的位置
    if (current_pointer == 0)
    {
        last_record_index = MAX_RECORDS - 1; // 指针在0，最新数据在最后位置
    }
    else
    {
        last_record_index = current_pointer - 1; // 最新数据在指针前一位置
    }

    // 3. 计算读取地址
    read_address = DATA_STORAGE_START + (last_record_index * RECORD_SIZE);

    // 4. 读取数据
    Int_24C256_ReadData(read_address, (uint8_t *)&record, RECORD_SIZE);

    // 5. 校验数据完整性
    uint32_t calculated_checksum = Calculate_Checksum(&record);
    if (calculated_checksum != record.checksum)
    {
        debug_printfln("Data corrupted at address 0x%04X", read_address);
        return 0; // 数据损坏
    }

    // 6. 转换回浮点数并返回数据
    *circle = record.circle_count;
    *part_int = Int_To_Float(record.part_int);
    *displacement = Int_To_Float(record.displacement_int);

    debug_printfln("Data loaded: circle=%d, angle=%.2f, disp=%.2f",
                   *circle, *part_int, *displacement);
    return 1; // 成功
}

// 初始化存储系统
void Int_24C256_Storage_Init(void)
{
    uint8_t pointer;

    // 初始化24C256
    Int_24C256_Init();

    // 读取指针
    Int_24C256_ReadData(POINTER_ADDRESS, &pointer, 1);

    // 如果指针无效，重置为0
    if (pointer >= MAX_RECORDS)
    {
        pointer = 0;
        Int_24C256_WriteData(POINTER_ADDRESS, &pointer, 1);
        debug_printfln("EEPROM pointer reset to 0");
    }

    debug_printfln("EEPROM storage initialized, current pointer: %d", pointer);
}

uint32_t Calculate_Checksum(DataRecord_t *record)
{
    uint32_t sum = 0;
    uint8_t *data = (uint8_t *)record;

    // 计算前12字节的校验和（不包括checksum字段）
    for (int i = 0; i < 12; i++)
    {
        sum += data[i];
    }
    return sum;
}

void Int_24C256_Init(void)
{
    I2C_init();
}

void Int_24C256_WriteByte(uint16_t Addr, uint8_t Data)
{
    I2C_Start();

    I2C_SendByte(EEPROM_ADDR << 1);
    // 等待应答
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 发送高位地址
    I2C_SendByte((Addr >> 8) & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    I2C_SendByte(Addr & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    I2C_SendByte(Data);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    I2C_Stop();

    Delay_ms(5);
}

uint8_t Int_24C256_ReadByte(uint16_t Addr)
{
    uint8_t data;

    // 发送起始信号
    I2C_Start();

    // 发送设备地址 + 写操作 (0xA0)
    I2C_SendByte(EEPROM_ADDR << 1);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return 0;
    }

    // 发送地址高字节
    I2C_SendByte((Addr >> 8) & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return 0;
    }

    // 发送地址低字节
    I2C_SendByte(Addr & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return 0;
    }

    // 重新启动
    I2C_Start();

    // 发送设备地址 + 读操作 (0xA1)
    I2C_SendByte((EEPROM_ADDR << 1) | 0x01);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return 0;
    }

    // 读取数据
    data = I2C_ReceiveByte();
    I2C_SendAck(1); // 发送非应答信号（结束读取）

    // 发送停止信号
    I2C_Stop();

    return data;
}

void Int_24C256_WritePage(uint16_t Addr, uint8_t *data, uint16_t len)
{
    uint16_t i;

    // 检查长度是否超过页大小
    if (len > 64)
        len = 64;

    // 确保地址在同一页面内
    uint16_t page_start = Addr & 0xFFC0; // 页面起始地址
    if ((Addr + len - 1) > (page_start + 63))
    {
        len = page_start + 64 - Addr; // 调整长度不超过页面边界
    }

    // 发送起始信号
    I2C_Start();

    // 发送设备地址 + 写操作 (0xA0)
    I2C_SendByte(EEPROM_ADDR << 1);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 发送地址高字节
    I2C_SendByte((Addr >> 8) & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 发送地址低字节
    I2C_SendByte(Addr & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 发送数据
    for (i = 0; i < len; i++)
    {
        I2C_SendByte(data[i]);
        if (I2C_ReceiveAck() != 0)
        {
            I2C_Stop();
            return;
        }
    }

    // 发送停止信号
    I2C_Stop();

    // 等待写入完成（最大5ms）
    Delay_ms(5);
}

void Int_24C256_WriteData(uint16_t Addr, uint8_t *data, uint16_t len)
{
    uint16_t written = 0;
    uint16_t current_addr = Addr;
    uint16_t remaining = len;
    uint16_t page_offset;
    uint16_t write_len;

    while (remaining > 0)
    {
        // 计算当前页内可写入的字节数
        page_offset = current_addr % 64;
        write_len = 64 - page_offset;

        if (write_len > remaining)
        {
            write_len = remaining;
        }

        // 写入一页数据
        Int_24C256_WritePage(current_addr, &data[written], write_len);

        written += write_len;
        current_addr += write_len;
        remaining -= write_len;
    }
}

void Int_24C256_ReadData(uint16_t Addr, uint8_t *buffer, uint16_t len)
{
    uint16_t i;

    // 发送起始信号
    I2C_Start();

    // 发送设备地址 + 写操作 (0xA0)
    I2C_SendByte(EEPROM_ADDR << 1);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 发送地址高字节
    I2C_SendByte((Addr >> 8) & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 发送地址低字节
    I2C_SendByte(Addr & 0xFF);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 重新启动
    I2C_Start();

    // 发送设备地址 + 读操作 (0xA1)
    I2C_SendByte((EEPROM_ADDR << 1) | 0x01);
    if (I2C_ReceiveAck() != 0)
    {
        I2C_Stop();
        return;
    }

    // 连续读取数据
    for (i = 0; i < len; i++)
    {
        buffer[i] = I2C_ReceiveByte();
        if (i == (len - 1))
        {
            I2C_SendAck(1); // 最后一个字节发送非应答
        }
        else
        {
            I2C_SendAck(0); // 其他字节发送应答
        }
    }

    // 发送停止信号
    I2C_Stop();
}
